Skip to content

feat: add find line segment Intersection algorithm #1705

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed

feat: add find line segment Intersection algorithm #1705

wants to merge 3 commits into from

Conversation

saahil-mahato
Copy link

Open in Gitpod know more

Describe your change:

  • Add an algorithm?
  • Fix a bug or typo in an existing algorithm?
  • Documentation change?

Checklist:

  • I have read CONTRIBUTING.md.
  • This pull request is all my own work -- I have not plagiarized.
  • I know that pull requests will not be merged if they fail the automated tests.
  • This PR only changes one algorithm file. To ease review, please open separate PRs for separate algorithms.
  • All new JavaScript files are placed inside an existing directory.
  • All filenames should use the UpperCamelCase (PascalCase) style. There should be no spaces in filenames.
    Example:UserProfile.js is allowed but userprofile.js,Userprofile.js,user-Profile.js,userProfile.js are not
  • All new algorithms have a URL in their comments that points to Wikipedia or another similar explanation.
  • If this pull request resolves one or more open issues then the commit message contains Fixes: #{$ISSUE_NO}.

@codecov-commenter
Copy link

codecov-commenter commented Oct 2, 2024

Codecov Report

Attention: Patch coverage is 87.93970% with 24 lines in your changes missing coverage. Please review.

Project coverage is 84.69%. Comparing base (9010481) to head (49de7a5).
Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
Geometry/FindIntersections.js 87.93% 24 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1705      +/-   ##
==========================================
+ Coverage   84.65%   84.69%   +0.03%     
==========================================
  Files         378      379       +1     
  Lines       19744    19943     +199     
  Branches     2951     2981      +30     
==========================================
+ Hits        16715    16890     +175     
- Misses       3029     3053      +24     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

this.#activeSet.add(segment)

// Check for intersections with neighboring active segments
const neighbors = Array.from(this.#activeSet).filter(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this efficient in general? The active set might very well contain linearly many line segments meaning you get quadratic runtime? The crucial point of this algorithm is that active line segments are managed in a sorted set so you only have to check adjacent line segments in the sorted order.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've implemented Bently-Ottmann algorithm and improved the complexity to O((n+k) logn).

Copy link
Collaborator

@appgurueu appgurueu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this should not be a class, but rather a single function which takes a list of line segments and produces a list of their intersections (or similar). This should also not be called "plane sweep" since that's just a general technique, but rather "LineSegmentIntersections" or similar.

I'd also recommend testing against the brute-force method to have some more complicated test cases.

@saahil-mahato saahil-mahato changed the title feat: add plane sweep algorithm feat: add find Intersection algorithm Oct 8, 2024
@saahil-mahato saahil-mahato changed the title feat: add find Intersection algorithm feat: add find line segment Intersection algorithm Oct 8, 2024
@saahil-mahato
Copy link
Author

I have made changes. Please review and let me know if anything is missing. Thanks.

@@ -0,0 +1,199 @@
/**
* @typedef {Object} Point
Copy link
Collaborator

@appgurueu appgurueu Oct 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, and many of the other typedefs (Segment, Event, maybe Intersection) should probably be classes; the functions on them make sense as methods (for example a findIntersection method for Segment).

findIntersections should stay a function however.

If you decide to keep (some of) these as "implicit" "structs" for whatever reason, the create... functions are still useless boilerplate which should be removed (and definitely doesn't need to be tested).

if (event.types.includes('left')) {
event.segments.forEach((segment) => {
sweepLineStatus.push(segment)
sweepLineStatus.sort(compareSegmentsY)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is O(n log n), resulting in a total time complexity of O(n² log n), which is worse than the naive brute force algorithm.

As said, the sweep line status structure needs to use a sorted set / map data structure. There should be efficient implementations of some in this repo; you need to use one.

}

if (event.types.includes('intersection')) {
// Re-check all pairs of segments at this x-coordinate for intersections
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also suffers from poor time complexity: First we do a linear filtering, then we do a quadratic brute force finding of intersections.

})
})

describe('calculateIntersectionPoint', () => {
Copy link
Collaborator

@appgurueu appgurueu Oct 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only calculateIntersectionPoint, handlePotentialIntersection and findIntersections really need tests. The rest is practically trivial and also covered transitively by sufficiently complex tests of the latter.

})
})

describe('findIntersections', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This really needs better, interesting tests with a couple segments and a couple events happening. Ideally even large randomized tests against the brute force algorithm.

@saahil-mahato saahil-mahato closed this by deleting the head repository Oct 27, 2024
@appgurueu
Copy link
Collaborator

😕

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants